#ifndef GAMEENGINE_CORE_RESOURCE_RESOURCE_H
#define GAMEENGINE_CORE_RESOURCE_RESOURCE_H

#include <GameEngine/Core/core_settings.h>
#include <GameEngine/Core/Macros/macro_singleton.h>

#include <map>
#include <set>


#ifdef GAMEENGINE_NAMESPACES
namespace GameEngine {
#endif

//========================================================



//! Manages several resource contexts
/*!
 *  The resource manager handles a list of contexts in which resources are stored. Contexts are designed to remove
 *  ambiguities on resource; each context implements some reference/unreference operations for the resources.
 *
 *  The resource manager is templated by the type of resource it manages, the type that can be used for unique
 *  identifier to such a resource, and the type that indicates the context in which resource is available.
 */
template <class RESOURCEID, class CONTEXTID>
class ResourceManager {
	//! Typedef to handle this type of resource
	typedef ResourceManager<RESOURCEID,CONTEXTID> Self;
	GAMEENGINE_DECLARE_SINGLETON( Self )

public:
	template <class RESOURCE> bool reference_resource(const RESOURCE& resource);
	template <class RESOURCE> bool unreference_resource(const RESOURCE& resource);

private:
	ResourceManager<RESOURCEID,CONTEXTID>();

private:
	//! Resource context
	/*!
	 *  Contexts are designed to remove ambiguities on resource; each context implements some reference/unreference
	 *  operations for the resources.
	 */
	class ResourceContext {
		//! The resource manager class is friend of the resource context class because it must be able to access its context
		friend class ResourceManager<RESOURCEID,CONTEXTID>;

	public:
		ResourceContext(CONTEXTID context);
		virtual ~ResourceContext();

		template <class RESOURCE> bool reference_resource(const RESOURCE& resource);
		template <class RESOURCE> bool unreference_resource(const RESOURCE& resource);

		//! Inferior operator used to sort resource contexts
		bool operator<(const ResourceContext& rhs) const { return ( context_ < rhs.context_ ); }

	private:
		//! ID associated to this context
		CONTEXTID context_;

		//! List of resource IDs in this context
		std::map<RESOURCEID,unsigned int> resources_;
	};

private:
	//! List of available contexts
	std::set<ResourceContext> contexts_;
};

#ifdef GAMEENGINE_NAMESPACES
} // namespace GameEngine
#endif

#include <GameEngine/Core/Resource/resource.hpp>

#endif
